import 'package:flutter/foundation.dart';

/// [IgnorableChangeNotifier]内部新增了[_ignorableListeners],用于处理一些情况下修改[value],
/// 但是不通知[_ignorableListeners]内的监听
///
/// 当调用[IgnorableChangeNotifier.notifySomeListeners]时，只通知[ChangeNotifier._listeners]的监听
class IgnorableChangeNotifier extends ChangeNotifier {
  ObserverList<VoidCallback> _ignorableListeners = ObserverList<VoidCallback>();

  bool _debugAssertNotDisposed() {
    assert(() {
      if (_ignorableListeners == null) {
        AssertionError([
          'A $runtimeType was used after being disposed.',
          'Once you have called dispose() on a $runtimeType, it can no longer be used.'
        ]);
      }
      return true;
    }());
    return true;
  }

  @override
  bool get hasListeners {
    return super.hasListeners || _ignorableListeners.isNotEmpty;
  }

  void addIgnorableListener(listener) {
    assert(_debugAssertNotDisposed());
    _ignorableListeners.add(listener);
  }

  void removeIgnorableListener(listener) {
    assert(_debugAssertNotDisposed());
    _ignorableListeners.remove(listener);
  }

  @override
  void dispose() {
    _ignorableListeners = null;
    super.dispose();
  }

  /// 通知所有的listener，包括[ChangeNotifier._listeners]和[_ignorableListeners]
  @protected
  @override
  @visibleForTesting
  void notifyListeners() {
    super.notifyListeners();
    if (_ignorableListeners != null) {
      final List<VoidCallback> localListeners =
          List<VoidCallback>.from(_ignorableListeners);
      for (VoidCallback listener in localListeners) {
        try {
          if (_ignorableListeners.contains(listener)) {
            listener();
          }
        } catch (exception, stack) {
          FlutterError.reportError(
            FlutterErrorDetails(
              exception: exception,
              stack: stack,
              library: 'IgnorableChangeNotifier',
            ),
          );
        }
      }
    }
  }

  /// 仅通知[ChangeNotifier._listeners]，[_ignorableListeners]的监听不会被触发
  @protected
  void notifySomeListeners() {
    super.notifyListeners();
  }
}

/// [IgnorableChangeNotifier]的扩展，相当于[ValueNotifier]和[ChangeNotifier]的关系
class IgnorableValueNotifier<T> extends IgnorableChangeNotifier
    implements ValueListenable<T> {
  IgnorableValueNotifier(this._value);

  @override
  T get value => _value;
  T _value;

  set value(T newValue) {
    if (_value == newValue) {
      return;
    }
    _value = newValue;
    notifyListeners();
  }

  void updateIgnoring(T newValue) {
    if (_value == newValue) {
      return;
    }
    _value = newValue;
    notifySomeListeners();
  }

  void updateItself() {
    notifyListeners();
  }

  @override
  String toString() => '${describeIdentity(this)}($value)';
}
